package com.xiangxg.jvm.classloader;

import java.io.*;

public class MyTest16 extends ClassLoader{
    private String classLoaderName;

    private final String fileExtension = ".class";

    private String path;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public MyTest16(String classLoaderName){
        super();//将系统类加载器当做该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }
    public MyTest16(ClassLoader parent, String classLoaderName){
        super(parent);//显式指定该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }



    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        System.out.println("findClass invoke");
        System.out.println("class loader name : "+this.classLoaderName);
        byte [] data = this.loadClassData(className);
        return this.defineClass(className,data,0,data.length);
    }

    public MyTest16(ClassLoader classLoader){
        super(classLoader);
    }

    private byte[] loadClassData(String className){
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        className =  className.replace(".","\\");
        try {
            is = new FileInputStream(new File(this.path + className + this.fileExtension));
            baos = new ByteArrayOutputStream();
            int ch = 0;
            while (-1 != (ch = is.read())){
                baos.write(ch);
            }
            data = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                is.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    /**
     * 每个类都有自己的命名空间，命名空间由该加载器及所有父加载器所加载的类组成
     * 在同一个命名空间中，不会出现类的完整名字
     * 在不同的命名空间中，有可能出现类的完整名字
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception{
        MyTest16 loader1 = new MyTest16("loader1");
        loader1.setPath("C:\\java\\code\\");
        Class<?> clazz = loader1.loadClass("com.xiangxg.jvm.classloader.MyTest1");
        System.out.println("class: "+clazz.hashCode());
        Object object = clazz.newInstance();
        System.out.println(object);

        System.out.println("=========================");
        MyTest16 loader2 = new MyTest16(loader1,"loader2");
        loader2.setPath("C:\\java\\code\\");
        Class<?> clazz2 = loader2.loadClass("com.xiangxg.jvm.classloader.MyTest1");
        System.out.println("class: "+clazz2.hashCode());
        Object object2 = clazz2.newInstance();
        System.out.println(object2);

        System.out.println("=========================");
        MyTest16 loader3 = new MyTest16("loader2");
        loader3.setPath("C:\\java\\code\\");
        Class<?> clazz3 = loader3.loadClass("com.xiangxg.jvm.classloader.MyTest1");
        System.out.println("class: "+clazz3.hashCode());
        Object object3 = clazz3.newInstance();
        System.out.println(object3);

      /*  //类的卸载
        //-XX:+TraceClassUnloading
       loader1 = null;
        clazz = null;
        object = null;

        System.gc();
        Thread.sleep(20000);
        loader1 = new MyTest16("loader1");
        loader1.setPath("C:\\java\\code\\");
        clazz = loader1.loadClass("com.xiangxg.jvm.classloader.MyTest1");
        System.out.println("class: "+clazz.hashCode());
        object = clazz.newInstance();

       // System.gc();
        System.out.println(object);*/
    }

    public static void test(ClassLoader classLoader) throws Exception {

    }
}
